package redis.controller;

import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;

/**
 * @program: check-repetition
 * @description:
 * @author: hjk
 * @create: 2021-07-14 17:22
 **/
@RestController
@RequestMapping("/redisson")
public class RedisController {

    @Resource
    private RedissonClient redisson;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @ApiOperation(value="sss")
    @GetMapping("/sss")
    public String sss () throws InterruptedException {
        String name = Thread.currentThread().getName();
        //获取分布式锁，只要锁的名字一样，就是同一把锁
        RLock lock = redisson.getLock("lock");

        //加锁（阻塞等待），默认过期时间是30秒
        lock.lock();
        try{
            //如果业务执行过长，Redisson会自动给锁续期
            System.out.println(name + "加锁成功，执行业务逻辑");
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //解锁，如果业务执行完成，就不会继续续期，即使没有手动释放锁，在30秒过后，也会释放锁
            lock.unlock();
            System.out.println(name + "释放锁成功，执行业务逻辑");
        }
        return "success";
    }

    @RequestMapping("/write")
    public String write(){
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("wr-lock");
        RLock writeLock = readWriteLock.writeLock();
        String s = UUID.randomUUID().toString();
        writeLock.lock();
        try {
            redisTemplate.opsForValue().set("wr-lock-key", s);
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            writeLock.unlock();
        }
        return s;
    }

    @SneakyThrows
    @RequestMapping("/read")
    public String read(){
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("wr-lock");
        RLock readLock = readWriteLock.readLock();
        String s = "xxx";
        readLock.lock();
        try {
            s = redisTemplate.opsForValue().get("wr-lock-key");
        } finally {
            readLock.unlock();
        }
        return s;
    }

    @RequestMapping("/test")
    public String test(@RequestParam("current") Integer pageNum,@RequestParam("size") Integer pageSize){
        redisTemplate.opsForZSet().add("linkId:2", 1 +"", 11);
        redisTemplate.opsForZSet().add("linkId:2", 2 +"", 22);
        redisTemplate.opsForZSet().add("linkId:2", 3 +"", 33);
        redisTemplate.opsForZSet().add("linkId:2", 4 +"", 44);
        redisTemplate.opsForZSet().add("linkId:2", 5 +"", 55);
        redisTemplate.opsForZSet().add("linkId:2", 6 +"", 66);
        redisTemplate.opsForZSet().incrementScore("linkId:2", 7 +"", 1);
        redisTemplate.opsForZSet().incrementScore("linkId:2", 6 +"", 1);

        int start = pageSize * (pageNum - 1); // 因为redis中list元素位置基数是0
        int end = start + pageSize - 1;
        Set<ZSetOperations.TypedTuple<String>> typedTuples = redisTemplate.opsForZSet().reverseRangeWithScores("linkId:2", start, end);
        Iterator<ZSetOperations.TypedTuple<String>> iterator = typedTuples.iterator();
        if(iterator.hasNext()){
            ZSetOperations.TypedTuple<String> next = iterator.next();
            Double score = next.getScore();
            String value = next.getValue();
            System.out.println(score);
            System.out.println(value);
        }
        //System.err.println(range);
        return "success";
    }
}
